package com.fitso.model.dao.hibernate.type.measure;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

import com.fitso.model.bean.measure.Measure;

/**
 * Conversion utility to/from the database/java type of {@link Measure} types
 * 
 * @author timothystorm
 */
public abstract class MeasureHibernateType implements UserType {

	public Object assemble(Serializable cached, Object owner) throws HibernateException {
		return null;
	}

	public Object deepCopy(Object value) throws HibernateException {
		return null;
	}

	public Serializable disassemble(Object value) throws HibernateException {
		return null;
	}

	public boolean equals(Object o1, Object o2) throws HibernateException {
		if (o1 == null && o2 == null) {
			return true;
		}
		if ((o1 == null && o2 != null) || (o1 != null && o2 == null)) {
			return false;
		}
		return ((Measure) o1).equals((Measure) o2);
	}

	public int hashCode(Object o) throws HibernateException {
		return o.hashCode();
	}

	public boolean isMutable() {
		return true;
	}

	public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
		BigDecimal value = (BigDecimal) Hibernate.BIG_DECIMAL.nullSafeGet(rs, names[0]);
		return convertToMeasure(value);
	}

	public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException,
			SQLException {
		if (value != null) {
			BigDecimal measure = convertToBigDecimal((Measure) value);
			Hibernate.BIG_DECIMAL.nullSafeSet(statement, measure, index);
		} else {
			Hibernate.BIG_DECIMAL.nullSafeSet(statement, null, index);
		}
	}

	public int[] sqlTypes() {
		return new int[] { Types.DOUBLE };
	}

	public Object replace(Object original, Object target, Object owner) throws HibernateException {
		return copy((Measure) original);
	}

	abstract protected Measure copy(Measure value);

	abstract protected Measure convertToMeasure(BigDecimal value);

	abstract protected BigDecimal convertToBigDecimal(Measure value);
}
